#ifndef YIZHI_MUTEX_H
#define YIZHI_MUTEX_H

#include<thread>
#include<mutex>
#include<semaphore.h>
#include <iostream>
#include"noncapyable.h"
namespace Yizhi{

    /// @brief 信号量封装
    class Semaphore:public noncopyable{
        public:
        Semaphore(uint32_t value=0);
        void wait();
        void post();
        ~Semaphore();
        private:
        sem_t m_semaphore;
    };

    /// @brief 局部锁实现，构造加锁，析构解锁
    /// @tparam T 
    template<class T>
    struct ScopeLockImpl
    {   
        ScopeLockImpl(T& mutex)
        :m_mutex(mutex)
        ,m_locked(false){
            lock();
        }
        void lock(){
            if(!m_locked){
                m_locked=true;
                m_mutex.lock();
            }
        }
           
        void unlock(){
            if(m_locked){
                m_locked=false;
                m_mutex.unlock();
            }
            
        }
        ~ScopeLockImpl(){
           unlock();
        }

        T& m_mutex;
        bool m_locked;
    };

    /// @brief 互斥量封装
    class Mutex:public noncopyable{
        public:
        typedef ScopeLockImpl<Mutex> Lock;

        Mutex(){
            if(pthread_mutex_init(&m_mutex,NULL)!=0){
                throw std::logic_error("mutex_init errot");
            }
        }
        void lock(){
            if(pthread_mutex_lock(&m_mutex)!=0){
                throw std::logic_error("mutex_lock errot");
            }
        }
        void unlock(){
            if(pthread_mutex_unlock(&m_mutex)!=0){
                throw std::logic_error("mutex_unlock errot");
            }
        }

        ~Mutex(){
            if(pthread_mutex_destroy(&m_mutex)!=0){
                //throw std::logic_error("mutex_destory errot");
            }
        }
        private:
        pthread_mutex_t m_mutex;
    };
    
    /// @brief 局部读锁实现
    /// @tparam T 
    template<class T>
    class ReadMutexIml{
        public:
        ReadMutexIml(T& mutex)
        :m_mutex(mutex)
        ,m_locked(false){
            lock();
        }
        void unlock(){
            if(m_locked){
                m_locked=false;
                m_mutex.unlock();
            }
        }
        void lock(){
            if(!m_locked){
                m_locked=true;
                m_mutex.rdlock();
            }
        }
        ~ReadMutexIml(){
            unlock();
        }
        private:
        T &m_mutex;
        bool m_locked;
    };

    /// @brief 局部写锁实现
    /// @tparam T 
    template<class T>
    class WriteMutexIml{
        public:
        WriteMutexIml(T& mutex)
        :m_locked(false)
        ,m_mutex(mutex)
        {
            lock();
        }
        void lock(){
            if(!m_locked){
                m_locked=true;
                m_mutex.wrlock();
            }
        }
        void unlock(){
            if(m_locked){
                m_locked=false;
                m_mutex.unlock();
            }
        }
        ~WriteMutexIml(){
            unlock();
        }
        private:
        bool m_locked;
        T& m_mutex;
       
        
    };


    /// @brief 封装读写锁
    class RWMutex:noncopyable{
        public:
        typedef WriteMutexIml<RWMutex> WriteLock;
        typedef ReadMutexIml<RWMutex>  ReadLock;
        RWMutex(){
            if(pthread_rwlock_init(&m_mutex,nullptr)!=0){
                throw std::logic_error("rwmutex errot");
            }
        }

        void rdlock(){
            if( pthread_rwlock_rdlock(&m_mutex)!=0){
                throw std::logic_error("rwlock_rdlock error");
            }
           
        }
        void wrlock(){
            if( pthread_rwlock_wrlock(&m_mutex)!=0){
                throw std::logic_error("rwlock_wrlock errot");
            }
           
        }
        void unlock(){
            if( pthread_rwlock_unlock(&m_mutex)!=0){
                 std::cout<<"error unlock"<<std::endl;
                throw std::logic_error("unlock error");
            }
           
        }
        ~RWMutex(){
            if(  pthread_rwlock_destroy(&m_mutex)!=0){
               // throw std::logic_error("lock error");
               std::cout<<"error "<<std::endl;
            }
          
        }
        private:
        pthread_rwlock_t m_mutex;
    
    };



    
    
}
#endif